import re
import urlparse
import md5

from httpencode.http import HTTP
from BeautifulSoup import NavigableString
from shrubbery.template import Template, replaceable


class JsonTemplate(Template):
    """
    A template that can embbed JSON objects from URLs.
    """
    def __init__(self, soup, http=None, environ=None, *args, **kwargs):
        Template.__init__(self, soup, *args, **kwargs)

        self.http = http or HTTP()
        self.environ = environ

        self.data = self.retrieve()

    def process(self, data, remove_empty_nodes=True):
        data.update(self.data)
        return Template(unicode(self)).process(data, remove_empty_nodes)

    def retrieve(self):
        data = {}

        # Search for all URLs.
        regexp = re.compile(r"{(http.*?)}")

        # Replace nodes first.
        nodes = self.findAll(replaceable(regexp)) + self.findAll(text=regexp)

        def retriever(m):
            url = m.group(1) 
            resource, json = url.split("#", 1)
            repl = md5.new(resource).hexdigest()
            if repl not in data:
                try:
                    data[repl] = self.http.GET(resource,
                                               output="name json",
                                               wsgi_request=self.environ)
                except:
                    pass
            return "{%s.%s}" % (repl, json)
        
        for node in nodes:
            if isinstance(node, NavigableString):
                repl = regexp.sub(retriever, node.string)
                if node.parent: node.replaceWith(repl)
            else:
                if node.string:
                    repl = regexp.sub(retriever, node.string)
                    node.next.replaceWith(repl)
                for k, v in node.attrs:
                    node[k] = regexp.sub(retriever, v).strip()
                    if not node[k]: del node[k]

        return data
